﻿#ifndef MEPOINT_H
#define MEPOINT_H

#include <iostream>
#include <vector>
#include <math.h>

/**
 * @brief 3D点
 */
class MePoint3D
{
public:
    MePoint3D() {}
    MePoint3D(double value[3]) {
        v[0]=value[0];
        v[1]=value[1];
        v[2]=value[2];
    }
    /// 返回存放的数据
    double *data() { return v; }
    MePoint3D(double x, double y, double z) {
        v[0]=x;
        v[1]=y;
        v[2]=z;
    }
    void zero() {
        v[0]=0.0;
        v[1]=0.0;
        v[2]=0.0;
    }

    double norm() {
        return sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );
    }


    double &operator()(unsigned index) {
        return v[index];
    }
    double &operator[](unsigned index) {
        return v[index];
    }

    MePoint3D const operator + (MePoint3D const &p) {
        MePoint3D result;
        result.v[0] = v[0] + p.v[0];
        result.v[1] = v[1] + p.v[1];
        result.v[2] = v[2] + p.v[2];

        return result;
    }


    MePoint3D const& operator += (MePoint3D const &p) {
        *this = *this + p;
        return *this;
    }

    MePoint3D const operator - (MePoint3D const &p) {
        MePoint3D result;
        result.v[0] = v[0] - p.v[0];
        result.v[1] = v[1] - p.v[1];
        result.v[2] = v[2] - p.v[2];

        return result;
    }

    MePoint3D const& operator -= (MePoint3D const &p) {
        *this = *this - p;
        return *this;
    }

    MePoint3D const operator * (double const &scale) {
        MePoint3D result;
        result.v[0] = v[0] * scale;
        result.v[1] = v[1] * scale;
        result.v[2] = v[2] * scale;

        return result;
    }

    MePoint3D const& operator *= (double const &scale) {
        *this = *this * scale;
        return *this;
    }

    MePoint3D const operator / (double const &scale) {
        MePoint3D result;
        result.v[0] = v[0] / scale;
        result.v[1] = v[1] / scale;
        result.v[2] = v[2] / scale;

        return result;
    }

    MePoint3D const& operator /= (double const &scale) {
        *this = *this / scale;
        return *this;
    }

    //friend std::ostream &operator<<(std::ostream &os, MePoint3D &p);

    /// 计算两点间的距离
    static double distance(MePoint3D &pointa, MePoint3D &pointb) {
        double *a= pointa.v;
        double *b = pointb.v;
        return sqrt((b[0]-a[0])*(b[0]-a[0]) + (b[1]-a[1])*(b[1]-a[1]) + (b[2]-a[2])*(b[2]-a[2]));
    }
public:
    double v[3];
};


namespace { // define standard operator << 
inline std::ostream & operator<<
(
        std::ostream & stream,
        MePoint3D const &p
        )
{
    stream << p.v[0] << ", " << p.v[1] << ", " << p.v[2];
    return stream;
}


static inline
std::ostream& operator << (std::ostream& out, const std::vector<double>& vec)
{
    out << "[";
    unsigned int i;
    for (i =0; i < vec.size()-1; i++) {
        out << vec[i] << ", ";
    }
    out << vec[i] << "]";
    return out;
}

static inline
std::ostream& operator << (std::ostream& out, const std::vector<int>& vec)
{
    if (vec.size() == 0) {
        out << "[]";
    } else {
        out << "[";
        unsigned int i;
        for (i =0; i < vec.size()-1; i++) {
            out << vec[i] << ", ";
        }
        out << vec[i] << "]";
    }
    return out;
}

static inline
std::ostream& operator << (std::ostream& out, const std::vector<MePoint3D>& vec)
{
    if (vec.size() == 0) {
        out << "[]";
    } else {
        out << "[";
        unsigned int i;
        for (i =0; i < vec.size()-1; i++) {
            out << vec[i] << "; ";
        }
        out << vec[i] << "]";
    }
    return out;
}
}

//std::ostream &operator<<(std::ostream &os, MePoint3D &p)
//{
//    os << p.v[0] << ", " << p.v[1] << ", " << p.v[2];
//    return os;
//}

#endif // MEPOINT_H
